﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xunit;
using Moq;

namespace MvcWiki.Test.Service.WikiNamespaceService
{
    public class DeleteWikiNamespaceFacts
    {
        [Fact]
        public void Call()
        {
            var wikiNamespaceRepository = new Mock<MvcWiki.Repository.IWikiNamespaceRepository>();

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            repositoryFactory.Setup(x => x.GetWikiNamespaceRepository()).Returns(wikiNamespaceRepository.Object);

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var wikiUserProvider = new Mock<MvcWiki.User.IWikiUserProvider>();
            wikiUserProvider.Setup(x => x.CanDeleteNamespace(It.IsAny<MvcWiki.Model.WikiNamespace>())).Returns(true);

            var service = new MvcWiki.Service.WikiNamespaceService(repositoryFactory.Object, unitOfWork.Object, wikiUserProvider.Object);

            service.DeleteWikiNamespace("Namespace");
        }

        [Fact]
        public void Calls_IWikiNamespaceRepository_GetWikiNamespace()
        {
            var wikiNamespaceRepository = new Mock<MvcWiki.Repository.IWikiNamespaceRepository>();

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            repositoryFactory.Setup(x => x.GetWikiNamespaceRepository()).Returns(wikiNamespaceRepository.Object);

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var wikiUserProvider = new Mock<MvcWiki.User.IWikiUserProvider>();
            wikiUserProvider.Setup(x => x.CanDeleteNamespace(It.IsAny<MvcWiki.Model.WikiNamespace>())).Returns(true);

            var service = new MvcWiki.Service.WikiNamespaceService(repositoryFactory.Object, unitOfWork.Object, wikiUserProvider.Object);

            service.DeleteWikiNamespace("Namespace");

            wikiNamespaceRepository.Verify(x => x.GetWikiNamespace("Namespace"));
        }

        [Fact]
        public void Calls_IWikiNamespaceRepository_DeleteWikiNamespace()
        {
            var wikiNamespaceRepository = new Mock<MvcWiki.Repository.IWikiNamespaceRepository>();

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            repositoryFactory.Setup(x => x.GetWikiNamespaceRepository()).Returns(wikiNamespaceRepository.Object);

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var wikiUserProvider = new Mock<MvcWiki.User.IWikiUserProvider>();
            wikiUserProvider.Setup(x => x.CanDeleteNamespace(It.IsAny<MvcWiki.Model.WikiNamespace>())).Returns(true);

            var service = new MvcWiki.Service.WikiNamespaceService(repositoryFactory.Object, unitOfWork.Object, wikiUserProvider.Object);

            service.DeleteWikiNamespace("Namespace");

            wikiNamespaceRepository.Verify(x => x.DeleteWikiNamespace(It.IsAny<MvcWiki.Model.WikiNamespace>()));
        }

        [Fact]
        public void Calls_IWikiNamespaceRepository_DeleteWikiNamespace_With_WikiNamespace_Returned_From_GetWikiNamespace()
        {
            var wikiNamespace = new MvcWiki.Model.WikiNamespace { Name = "Namespace" };

            var wikiNamespaceRepository = new Mock<MvcWiki.Repository.IWikiNamespaceRepository>();
            wikiNamespaceRepository.Setup(x => x.GetWikiNamespace("Namespace")).Returns(wikiNamespace);

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            repositoryFactory.Setup(x => x.GetWikiNamespaceRepository()).Returns(wikiNamespaceRepository.Object);

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var wikiUserProvider = new Mock<MvcWiki.User.IWikiUserProvider>();
            wikiUserProvider.Setup(x => x.CanDeleteNamespace(It.IsAny<MvcWiki.Model.WikiNamespace>())).Returns(true);

            var service = new MvcWiki.Service.WikiNamespaceService(repositoryFactory.Object, unitOfWork.Object, wikiUserProvider.Object);

            service.DeleteWikiNamespace("Namespace");

            wikiNamespaceRepository.Verify(x => x.DeleteWikiNamespace(wikiNamespace));
        }

        [Fact]
        public void Calls_IUnitOfWork_Commit()
        {
            var wikiNamespaceRepository = new Mock<MvcWiki.Repository.IWikiNamespaceRepository>();

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            repositoryFactory.Setup(x => x.GetWikiNamespaceRepository()).Returns(wikiNamespaceRepository.Object);

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var wikiUserProvider = new Mock<MvcWiki.User.IWikiUserProvider>();
            wikiUserProvider.Setup(x => x.CanDeleteNamespace(It.IsAny<MvcWiki.Model.WikiNamespace>())).Returns(true);

            var service = new MvcWiki.Service.WikiNamespaceService(repositoryFactory.Object, unitOfWork.Object, wikiUserProvider.Object);

            service.DeleteWikiNamespace("Namespace");

            unitOfWork.Verify(x => x.Commit());
        }

        [Fact]
        public void Calls_WikiUserProvider_CanDeleteNamespace()
        {
            var wikiNamespaceRepository = new Mock<MvcWiki.Repository.IWikiNamespaceRepository>();

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            repositoryFactory.Setup(x => x.GetWikiNamespaceRepository()).Returns(wikiNamespaceRepository.Object);

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var wikiUserProvider = new Mock<MvcWiki.User.IWikiUserProvider>();
            wikiUserProvider.Setup(x => x.CanDeleteNamespace(It.IsAny<MvcWiki.Model.WikiNamespace>())).Returns(true);

            var service = new MvcWiki.Service.WikiNamespaceService(repositoryFactory.Object, unitOfWork.Object, wikiUserProvider.Object);

            service.DeleteWikiNamespace("Namespace");

            wikiUserProvider.Verify(
                x => x.CanDeleteNamespace(
                    It.IsAny<MvcWiki.Model.WikiNamespace>()));
        }

        [Fact]
        public void Throws_Exception_If_CanDeleteNamespace_Is_False()
        {
            var wikiNamespaceRepository = new Mock<MvcWiki.Repository.IWikiNamespaceRepository>();

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            repositoryFactory.Setup(x => x.GetWikiNamespaceRepository()).Returns(wikiNamespaceRepository.Object);

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var wikiUserProvider = new Mock<MvcWiki.User.IWikiUserProvider>();
            wikiUserProvider.Setup(x => x.CanDeleteNamespace(It.IsAny<MvcWiki.Model.WikiNamespace>())).Returns(false);

            var service = new MvcWiki.Service.WikiNamespaceService(repositoryFactory.Object, unitOfWork.Object, wikiUserProvider.Object);

            Assert.Throws<MvcWiki.Exceptions.AuthorizationException>(
                () => service.DeleteWikiNamespace("Namespace"));
        }
    }
}
